package com.leaguefox.domain.dao;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.transaction.annotation.Transactional;

public abstract class GenericDao<T, TPrimaryKey> {

	@PersistenceContext
	private transient EntityManager entityManager;

	protected abstract Class<T> getObjectClass();

	protected abstract TPrimaryKey getObjectPrimaryKey(T object);

	@Transactional
	public void persist(T object) {
		if (this.entityManager == null)
			this.entityManager = entityManager();
		this.entityManager.persist(object);
	}

	@Transactional
	public void remove(T object) {
		if (this.entityManager == null)
			this.entityManager = entityManager();
		if (this.entityManager.contains(object)) {
			this.entityManager.remove(object);
		} else {
			T attached = this.entityManager.find(getObjectClass(),
					getObjectPrimaryKey(object));
			this.entityManager.remove(attached);
		}
	}

	@Transactional
	public void flush() {
		if (this.entityManager == null)
			this.entityManager = entityManager();
		this.entityManager.flush();
	}

	@Transactional
	public T merge(T object) {
		if (this.entityManager == null)
			this.entityManager = entityManager();
		T merged = this.entityManager.merge(object);
		this.entityManager.flush();
		return merged;
	}

	public EntityManager entityManager() {
		return this.entityManager;
	}

	public long count() {
		return ((Number) entityManager().createQuery(
				"select count(o) from " + getObjectClass().getCanonicalName()
						+ " o").getSingleResult()).longValue();
	}

	@SuppressWarnings("unchecked")
	public List<T> findAll() {
		return entityManager().createQuery(
				"select o from " + getObjectClass().getCanonicalName() + " o")
				.getResultList();
	}

	public T find(TPrimaryKey id) {
		if (id == null)
			return null;
		return entityManager().find(getObjectClass(), id);
	}

	@SuppressWarnings("unchecked")
	public List<T> findEntries(int firstResult, int maxResults) {
		return entityManager().createQuery(
				"select o from " + getObjectClass().getCanonicalName() + " o")
				.setFirstResult(firstResult).setMaxResults(maxResults)
				.getResultList();
	}
}
